package mugen.ro;

import java.util.ArrayList;
import java.util.List;

import mugen.ro.CharStats.Stat;
import org.testng.internal.junit.ArrayAsserts;

import mugen.ro.Formulas.Size;

public class Formulas {
	
	public static Double getPPchangeBonus(int str, int dex){
		return str/2.0 + dex/4.0;
		
	}
	
	public static int getStatsForLvl(int lvl){
		Double stats = 100.0;
		for(int i =1; i<lvl;i++){
		if(i < 100)
			stats += Math.floor(i/5.0)+3;
		else
			stats += Math.floor(i/10.0)+13;
		}
		return stats.intValue();
			
		
	}
        /*public static int getStatsForLvl(CharStats cs){
        int stats = getStatsForLvl(cs.level);
        int[] costs = getStatCosts();
        stats-=
        return stats;
        }*/
	public static final int MAXSTAT = 120;
	public static int[] getStatCosts(){
		int[] smth = new int[MAXSTAT+1];
		int cost = 0;
		
		/*
		Raising a stat from x to x+1 costs [Floor((x-1) / 10)] + 2 points. (For x = 1,2,3,...,98,99)
		Raising a stat from 1 to 99 costs a total of 628 stat points.
		Raising a stat from 100 to 120 is possible for 3rd class only and cost more stat points.
		Raising a stat from x to x+1 costs [Floor((x-100) / 5)]*4 + 16 points. (For x = 100,101,...,119) 
		*/
		for(int a = 1; a< MAXSTAT; a++){
			
			if(a<100){
				cost += Math.floor((a-1)/10.0)+2;				
			}else{
				cost += Math.floor((a-100)/5.0)*4+16;
			}
			smth[a+1] = cost;
		}
		return smth;
		
		
	}
	
	public static Double getTotalAtk(Integer str, Integer dex, Integer luk, Integer lvl, Integer weaponAtk, Integer weaponLvl, Size size, Integer upgrade, Double cardBonus, Integer atkBonus){
		Double sAtk = sAtk(str, dex, luk, lvl);
		Double wAtk = wATK(weaponAtk, weaponLvl, str, size, upgrade, cardBonus);
		Double eAtk = qATK(atkBonus, cardBonus);
		return sAtk*2 + wAtk+eAtk;
	}
        public static Double getTotalAtk(CharStats cs){
                        int stre = cs.minimalStats.get(Stat.STR)+cs.statBonuses.get(Stat.STR);
			int dext = cs.minimalStats.get(Stat.DEX)+cs.statBonuses.get(Stat.DEX);
			int luck = cs.minimalStats.get(Stat.LUK)+cs.statBonuses.get(Stat.LUK);
                        //Double ppc = getPPchangeBonus(stre, dext);
                        Double ppc = cs.ppchange?getPPchangeBonus(stre, dext):0;
                        return getTotalAtk(stre, dext, luck, cs.level, cs.weaponAtk, cs.weaponLvl, Size.LARGE, cs.weaponUpgrade, cs.cardDmgModifier, cs.quipAtk+ppc.intValue());
        
        }
/*	public static Double getTotalAtkNew(Integer str, Integer dex, Integer luk, Integer lvl, Integer weaponAtk, Integer weaponLvl, Size size, Integer upgrade, Double cardBonus, Integer atkBonus){
		
		
	}
	public static Double calcModifiers(Double atk, Double race, Double element, Double Size){
		atk = Math.floor(atk*(1+race));
		
	}*/
	
	
	
	public static Double sAtk(Integer str, Integer dex, Integer luk,Integer lvl){
		return (Double) Math.floor(lvl/4.0 + str + dex/5.0 + luk/3.0); 
		
	}
	public enum Size { MEDIUM, SMALL, LARGE};
	
	public static Double refinementBonus(Integer weaponLvl,Integer weaponUpgrade) {
		Double refinementBonus = 0.0;
		switch (weaponLvl) {
		case 1:
			refinementBonus = weaponUpgrade*2.0;
			if(weaponUpgrade>5) refinementBonus += (weaponUpgrade-5)*1.5;
			break;
		case 2:
			refinementBonus = weaponUpgrade*3.0;
			if(weaponUpgrade>5) refinementBonus += (weaponUpgrade-5)*2.5;
			break;
		case 3:
			refinementBonus = weaponUpgrade*5.0;
			if(weaponUpgrade>5) refinementBonus += (weaponUpgrade-5)*3.5;
			break;
		case 4:
			refinementBonus = weaponUpgrade*7.0;
			if(weaponUpgrade>5) refinementBonus += (weaponUpgrade-5)*6.5;
			break;

		default:
			break;
		}
		return refinementBonus;
	}
	
	//public static Double minWATK(Integer weaponAtk,Integer weaponLvl,Integer str,Size size,Integer upgrade,Double itemBonus){}
	
	//public static Double maxWATK(Integer weaponAtk,Integer weaponLvl,Integer str,Size size,Integer upgrade,Double itemBonus){}
	
	public static Double wATK(Integer weaponAtk,Integer weaponLvl,Integer str,Size size,Integer upgrade,Double itemBonus){
		Double variance = 0.5*weaponLvl*weaponAtk;
		Double strBonus = weaponAtk*(str/200.0);
		Double refinementBonus = refinementBonus(weaponLvl,upgrade);
		Double totalAtk = (weaponAtk + strBonus + refinementBonus)*1*(1+itemBonus);
		return totalAtk;			
		
	}
	public static Double qATK(Integer atkBonus,Double cardBonus ){
		return atkBonus*(1+cardBonus);
		
	}
	
//	(Base Weapon ATK + Variance + STR Bonus + Refinement Bonus)*Size Penalty 
			
	
	
	public static Float totalAtk(Integer sATK,Float wATK,Float eATK){
		return sATK * 2 + wATK + eATK;		
	}
	
	
	public static Double asuraDmg(Double maxSp,Double atk){
		return atk*(8+maxSp/10);
	}
        
	private static final double JOBGAIN = 4.0;
	public static Double getMaxSp(Double multiplicativeBonusesSum, Double additiveBonusesSum, Integer lvl, Double totalInt ){
		Double baseSp = 10.0; 
		baseSp += lvl*JOBGAIN;
		Double maxSp = baseSp;
                maxSp = Math.floor(maxSp*1.25);
		//maxSp = Math.floor(maxSp*(1+totalInt*0.01));
                maxSp +=  Math.floor(maxSp*totalInt*0.01);
                //Double.valueOf(Math.round(
		maxSp += Math.floor(additiveBonusesSum*1.25);
                maxSp += Math.floor(maxSp*multiplicativeBonusesSum*0.01);
                //maxSp = Math.floor(maxSp*(1+multiplicativeBonusesSum*0.01));		
                
		
		
		return maxSp;
		
	}
        public static Double getMaxSp(CharStats cs){
        Double tint = new Double(cs.minimalStats.get(Stat.INT)+cs.statBonuses.get(Stat.INT));
        return getMaxSp(cs.spModifier, cs.spAdded, cs.level, tint);
        }
	
	
}
